package com.ssy.lingxi.product.serviceImpl;

import cn.hutool.core.util.ObjectUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.component.redis.service.IRedisStringUtils;
import com.ssy.lingxi.feign.UploadControllerFeign;
import com.ssy.lingxi.product.api.model.request.warehouse.*;
import com.ssy.lingxi.product.api.model.response.warehouse.InvoicesDetailsOrderResponse;
import com.ssy.lingxi.product.api.model.response.warehouse.InvoicesDetailsResponse;
import com.ssy.lingxi.product.common.InvoicesTypeConstant;
import com.ssy.lingxi.product.common.constant.ReviewConstant;
import com.ssy.lingxi.product.common.constant.StateConstant;
import com.ssy.lingxi.product.entity.Brand;
import com.ssy.lingxi.product.entity.material.MaterialGroup;
import com.ssy.lingxi.product.entity.warehouse.*;
import com.ssy.lingxi.product.api.model.response.warehouse.InvoicesListResponse;
import com.ssy.lingxi.product.repository.material.MaterialGroupRepository;
import com.ssy.lingxi.product.repository.warehouse.*;
import com.ssy.lingxi.product.service.InvoicesService;
import com.ssy.lingxi.product.serviceImpl.saleorder.InvoicesFactoryForStrategy;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.io.*;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 单据管理业务层
 *
 * @author wrc
 * @date 2020/6/30
 */
@Slf4j
@Service
public class InvoicesServiceImpl implements InvoicesService {

    @Resource
    IRedisStringUtils redisStringUtils;

    @Resource
    InvoicesRepository invoicesRepository;

    @Resource
    UploadControllerFeign uploadControllerFeign;

    @Resource
    InvoicesDetailsRepository invoicesDetailsRepository;

    @Resource
    InventoryRepository inventoryRepository;

    @Resource
    InvoicesTypeRepository invoicesTypeRepository;

    @Resource
    InvoicesImportBatchNoRepository invoicesImportBatchNoRepository;

    @Resource
    WarehouseRepository warehouseRepository;

    @Resource
    MaterialGroupRepository materialGroupRepository;

    @Resource
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Resource
    InvoicesFactoryForStrategy invoicesFactoryForStrategy;

    //数据导入批次号rediskey
    private static final String redisKey = "WAREHOUSE-SERVICE:BATCHNUMBER:";

    /**
     * 查询单据列表
     *
     * @author wrc
     * @date 2020/6/30
     */
    @Override
    public Wrapper<PageData<InvoicesListResponse>> invoicesList(InvoicesListRequest request, UserLoginCacheDTO sysUser) {
        Pageable page = PageRequest.of(request.getCurrent() - 1, request.getPageSize(), Sort.by("updateTime").descending());
        Page<Invoices> pageList = invoicesRepository.findAll((Specification<Invoices>) (root, query, cb) -> {
            List<Predicate> predicateList = new ArrayList<>();
            predicateList.add(cb.equal(root.get("memberId"), sysUser.getMemberId()));
            predicateList.add(cb.equal(root.get("memberRoleId"), sysUser.getMemberRoleId()));

            if (StringUtils.isNotEmpty(request.getInvoicesNo())) {
                predicateList.add(cb.equal(root.get("invoicesNo"), request.getInvoicesNo()));
            }

            if (StringUtils.isNotEmpty(request.getInvoicesAbstract())) {
                predicateList.add(cb.like(root.get("invoicesAbstract"), "%" + request.getInvoicesAbstract() + "%"));
            }

            if (Objects.nonNull(request.getInvoicesTypeId())) {
                predicateList.add(cb.equal(root.get("invoicesType").as(InvoicesType.class), request.getInvoicesTypeId()));
            }

            if (Objects.nonNull(request.getWarehouseId())) {
                predicateList.add(cb.equal(root.get("warehouse").as(Warehouse.class), request.getWarehouseId()));
            }

            if (Objects.nonNull(request.getState())) {
                predicateList.add(cb.equal(root.get("state"), request.getState()));
            }

            if (Objects.nonNull(request.getInvoicesTimeStart())) {
                predicateList.add(cb.greaterThanOrEqualTo(root.get("invoicesTime"), request.getInvoicesTimeStart()));
            }

            if (Objects.nonNull(request.getInvoicesTimeEnd())) {
                predicateList.add(cb.lessThanOrEqualTo(root.get("invoicesTime"), request.getInvoicesTimeEnd()));
            }

            Predicate[] p = new Predicate[predicateList.size()];
            return query.where(predicateList.toArray(p)).getRestriction();
        }, page);

        List<InvoicesListResponse> resultList = pageList.stream().map(invoices -> {
            InvoicesListResponse response = new InvoicesListResponse();
            BeanUtils.copyProperties(invoices, response);
            response.setInvoicesTypeId(invoices.getInvoicesType().getId());
            response.setInvoicesTypeName(invoices.getInvoicesType().getName());
            response.setWarehouseId(invoices.getWarehouse().getId());
            response.setWarehouseName(invoices.getWarehouse().getName());
            return response;
        }).collect(Collectors.toList());
        return Wrapper.success(new PageData<>(pageList.getTotalElements(), resultList));
    }

//    /**
//     * 数据导入
//     *
//     * @author wrc
//     * @date 2020/7/3
//     */
//    @Override
//    public Wrapper importExcel(MultipartFile file) {
//        List<Map<String, String>> excelData = ExcelUtil.getExcelData(file);
//        List<Invoices> list = new ArrayList<>();
//        assert excelData != null;
//        excelData.forEach(map -> {
//            Invoices invoices = new Invoices();
//            invoices.setId(Double.valueOf(map.get("id")).longValue());
//            list.add(invoices);
//        });
//        //保存到数据库
//        List<Invoices> invoicess = invoicesRepository.saveAll(list);
//        Set<Long> collect = invoicess.stream().map(Invoices::getId).collect(Collectors.toSet());
//        //记录批次号和导入的单据数据ID集合
//        String batchNumber = getBatchNumber();
//        InvoicesImportBatchNo invoicesImportBatchNo = new InvoicesImportBatchNo();
//        invoicesImportBatchNo.setBatchNo(batchNumber);
//        try {
//            invoicesImportBatchNo.setIdsJson(objectMapper.writeValueAsString(collect));
//        } catch (JsonProcessingException e) {
//            log.error("JSON转换异常", e);
//        }
//        invoicesImportBatchNoRepository.save(invoicesImportBatchNo);
//        return Wrapper.success();
//    }
//
//    /**
//     * 数据导入检查
//     *
//     * @author wrc
//     * @date 2020/7/3
//     */
//    @Override
//    public Wrapper importExcelCheck(MultipartFile file) {
//        //系统将错误数据生成日志（日志要说明是哪一个单据号、哪一个货号的数据，错误字段名称，错误原因
//        List<Map<String, String>> excelData = ExcelUtil.getExcelData(file);
//        if (null == excelData) {
//            return Wrapper.fail(ResponseCode.FILE_CONTENT_NULL);
//        }
//        String url = "";
//        for (int i = 0; i < excelData.size(); i++) {
//            //字段为null
//            if (null == excelData.get(i).get("id") || "".equals(excelData.get(i).get("id"))) {
//                //把数据写入文件
//                try {
//                    url = writeErorToTxt("错误行号：" + i + ",错误字段是：id" + ",错误原因：ID不能为空");
//                } catch (Exception e) {
//                    log.error("数据导入检查异常", e);
//                }
//                return Wrapper.success(url);
//            }
//        }
//        return Wrapper.success();
//    }

    /**
     * 单据单个删除/批量删除
     *
     * @author wrc
     * @date 2020/7/6
     */
    @Transactional
    @Override
    public Wrapper<Void> invoicesDelete(InvoicesDeleteRequest request) {
        //批量查询单据信息
        List<Invoices> invoicesList = invoicesRepository.findAllById(request.getIds());
        if(invoicesList.stream().anyMatch(
                o -> o.getState().equals(StateConstant.State.YES_EXAMINE))){
            return Wrapper.fail(ResponseCode.INVOICES_TYPE_NOT_DELETE);
        }
        List<InvoicesDetails> invoicesDetailsList = new ArrayList<>();
        invoicesList.stream().forEach(invoices -> {
            invoicesDetailsList.addAll(invoices.getInvoicesDetailsList());
        });
        invoicesRepository.deleteAllByIdIn(request.getIds());
        invoicesDetailsRepository.deleteAll(invoicesDetailsList);
        return Wrapper.success();
    }

    /**
     * 单据单个审核/批量审核
     * 单据单个反审/批量反审
     * @param request
     * @return
     */
    @Transactional
    @Override
    public Wrapper<Void> invoicesReview(InvoicesReviewRequest request) {
        //批量查询单据信息
        List<Invoices> invoicesList = invoicesRepository.findAllById(request.getIds());
        if(request.getReviewType().compareTo(ReviewConstant.ReviewType.REVIEW) == 0){
            //判断是否是未审核数据
            if(invoicesList.stream().anyMatch(
                    o -> o.getState().equals(StateConstant.State.YES_EXAMINE))){
                return Wrapper.fail(ResponseCode.INVOICES_STATE_YET_AUDIT);
            }
            //修改审查状态为已审核
            invoicesList.stream().forEach(invoices -> invoices.setState(StateConstant.State.YES_EXAMINE));
        }else{
            //判断是否是已审核数据
            if(invoicesList.stream().anyMatch(
                    o -> o.getState().equals(StateConstant.State.NOT_EXAMINE))){
                return Wrapper.fail(ResponseCode.INVOICES_STATE_NOT_AUDIT);
            }
            //修改审查状态为未审核
            invoicesList.stream().forEach(invoices -> invoices.setState(StateConstant.State.NOT_EXAMINE));
        }
        //审核：判断库存是否为0,如果为0且单据单据类型为出库，则不能审核出库
        //反审：判断库存是否为0,如果为0且单据单据类型为入库，则不能反审入库
        judge(invoicesList, request.getReviewType());
        updateInventory(invoicesList, request.getReviewType());
        invoicesRepository.saveAll(invoicesList);
        return Wrapper.success();
    }

    private void judge(List<Invoices> invoicesList, Integer reviewType) {
        List<InvoicesDetails> invoicesDetailsList = new ArrayList<>();
        invoicesList.stream().forEach(invoices -> {
            invoicesDetailsList.addAll(invoices.getInvoicesDetailsList());
        });
        List<Long> goodsIdList = invoicesDetailsList.stream().map(InvoicesDetails::getGoodsId).collect(Collectors.toList());
        //根据物料id和仓库id查询库存列表
        List<Inventory> inventoryList = inventoryRepository.findAllByGoodsIdInAndWarehouseIdIn(goodsIdList, invoicesList.stream().map(Invoices::getWarehouse).map(Warehouse::getId).collect(Collectors.toList()));
        if(reviewType.equals(ReviewConstant.ReviewType.REVIEW)) {
            //不存在库存时，不可以直接审核出库
            if (ObjectUtil.isEmpty(inventoryList)) {
                if (invoicesList.stream().anyMatch(
                        o -> InvoicesTypeConstant.InvoicesType.OUTGOING.equals(o.getInvoicesType().getDirection()))) {
                    throw new BusinessException(ResponseCode.BUSINESS_ERROR, "库存为0不能进行审核出库");
                }
            } else {  //存在库存时，库存为0或者库存不足时也不可以直接审核出库
                invoicesDetailsList.stream().forEach(invoicesDetails -> {
                    Inventory inventoryCurrent = inventoryList.stream().filter(inventory -> inventory.getWarehouseId().equals(invoicesDetails.getInvoices().getWarehouse().getId())
                            && inventory.getGoodsId().equals(invoicesDetails.getGoodsId())).findFirst().orElse(null);
                    if (InvoicesTypeConstant.InvoicesType.OUTGOING.equals(invoicesDetails.getInvoices().getInvoicesType().getDirection())) {
                        if (inventoryCurrent.getInventoryCount().compareTo(BigDecimal.ZERO) == 0) {
                            throw new BusinessException(ResponseCode.BUSINESS_ERROR, "库存为0不能进行审核出库");
                        } else if (inventoryCurrent.getInventoryCount().compareTo(invoicesDetails.getInvoicesCount()) < 0) {
                            throw new BusinessException(ResponseCode.BUSINESS_ERROR, "库存不足不能进行审核出库");
                        }
                    }
                });
            }
        }else{
            //不存在库存时，不可以直接反审入库
            if (ObjectUtil.isEmpty(inventoryList)) {
                if (invoicesList.stream().anyMatch(
                        o -> InvoicesTypeConstant.InvoicesType.STORAGE.equals(o.getInvoicesType().getDirection()))) {
                    throw new BusinessException(ResponseCode.BUSINESS_ERROR, "库存为0不能进行反审入库");
                }
            } else {  //存在库存时，库存为0或者库存不足时也不可以直接反审入库
                invoicesDetailsList.stream().forEach(invoicesDetails -> {
                    Inventory inventoryCurrent = inventoryList.stream().filter(inventory -> inventory.getWarehouseId().equals(invoicesDetails.getInvoices().getWarehouse().getId())
                            && inventory.getGoodsId().equals(invoicesDetails.getGoodsId())).findFirst().orElse(null);
                    if (InvoicesTypeConstant.InvoicesType.STORAGE.equals(invoicesDetails.getInvoices().getInvoicesType().getDirection())) {
                        if (inventoryCurrent.getInventoryCount().compareTo(BigDecimal.ZERO) == 0) {
                            throw new BusinessException(ResponseCode.BUSINESS_ERROR, "库存为0不能进行反审入库");
                        } else if (inventoryCurrent.getInventoryCount().compareTo(invoicesDetails.getInvoicesCount()) < 0) {
                            throw new BusinessException(ResponseCode.BUSINESS_ERROR, "库存不足不能进行反审入库");
                        }
                    }
                });
            }
        }

    }

    /**
     * 根据单据集合更新库存
     */
    private void updateInventory(List<Invoices> invoicesList, Integer reviewType) {
        //根据单据id获得单据详情
        List<InvoicesDetails> invoicesDetailss = invoicesDetailsRepository.findAllByInvoicesIdIn(invoicesList.stream().map(Invoices::getId).collect(Collectors.toList()));
        //根据单据ID分组
        Map<Long, List<InvoicesDetails>> invoicesDetailsMap = invoicesDetailss.stream().collect(Collectors.groupingBy(invoicesDetails -> invoicesDetails.getInvoices().getId()));
        List<Inventory> inventoryList = new ArrayList<>();
        invoicesList.stream().forEach(invoices -> {
            //单据明细集合
            List<InvoicesDetails> invoicesDetailsList = invoicesDetailsMap.get(invoices.getId());
            List<Inventory> list = invoicesDetailsList.stream().map(invoicesDetails -> {
                //根据物料id和仓库id判断是否存在库存数据
                Inventory inventory = inventoryRepository.findFirstByGoodsIdAndWarehouseId(invoicesDetails.getGoodsId(), invoices.getWarehouse().getId());
                if (null == inventory) {
                    inventory = new Inventory();
                    BeanUtils.copyProperties(invoicesDetails, inventory, "id");
                    inventory.setWarehouseId(invoices.getWarehouse().getId());
                    inventory.setMemberId(invoices.getMemberId());
                    inventory.setMemberRoleId(invoices.getMemberRoleId());
                    inventory.setCreateTime(System.currentTimeMillis());
                    inventory.setSafeInventoryCount(BigDecimal.valueOf(0));
                    inventory.setDirection(invoices.getInvoicesType().getDirection());
                    //如果不存在库存记录，直接将库存设置为单据数量
                    inventory.setInventoryCount(invoicesDetails.getInvoicesCount());
                }else {
                    //审核类型：0.反审 ->> 入库-减少库存     1.审核 ->> 入库-增加库存
                    if (InvoicesTypeConstant.InvoicesType.STORAGE.equals(invoices.getInvoicesType().getDirection())) {
                        inventory.setInventoryCount(reviewType.equals(ReviewConstant.ReviewType.REVIEW) ? Optional.ofNullable(inventory.getInventoryCount()).orElse(BigDecimal.valueOf(0)).add(invoicesDetails.getInvoicesCount()) : Optional.ofNullable(inventory.getInventoryCount()).orElse(BigDecimal.valueOf(0)).subtract(invoicesDetails.getInvoicesCount()));
                    }
                    //审核类型：0.反审 ->> 出库-增加库存     1.审核 ->> 出库-减少库存
                    else if(InvoicesTypeConstant.InvoicesType.OUTGOING.equals(invoices.getInvoicesType().getDirection())) {
                        inventory.setInventoryCount(reviewType.equals(ReviewConstant.ReviewType.REVIEW) ? Optional.ofNullable(inventory.getInventoryCount()).orElse(BigDecimal.valueOf(0)).subtract(invoicesDetails.getInvoicesCount()) : Optional.ofNullable(inventory.getInventoryCount()).orElse(BigDecimal.valueOf(0)).add(invoicesDetails.getInvoicesCount()));
                    }
                }
                inventory.setInvoicesCount(inventory.getInventoryCount());
                inventory.setTotalPrice(inventory.getInventoryCount().multiply(inventory.getCostPrice()));
                inventory.setUpdateTime(System.currentTimeMillis());
                return inventory;
            }).collect(Collectors.toList());
            inventoryList.addAll(list);
        });
        inventoryRepository.saveAll(inventoryList);
    }

    /**
     * 查询导入批次号列表
     *
     * @author wrc
     * @date 2020/7/7
     */
    @Override
    public Wrapper<List<InvoicesImportBatchNo>> invoicesImportBatchList(InvoicesImportBatchListRequest request) {
        InvoicesImportBatchNo invoices = new InvoicesImportBatchNo();
        invoices.setBatchNo(request.getBatchNo());
        Example<InvoicesImportBatchNo> example = Example.of(invoices);
        Sort.Order order = Sort.Order.desc("batchNo");
        Sort sort = Sort.by(order);
        List<InvoicesImportBatchNo> all = invoicesImportBatchNoRepository.findAll(example, sort);
        return Wrapper.success(all);
    }

    /**
     * 删除批次号并且删除导入的未审核的单据数据
     *
     * @author wrc
     * @date 2020/7/7
     */
    @Transactional
    @Override
    public Wrapper invoicesImportBatchDelete(InvoicesImportBatchDeleteRequest request) {
        Optional<InvoicesImportBatchNo> byId = invoicesImportBatchNoRepository.findById(request.getId());
        if (!byId.isPresent()) {
            return Wrapper.fail(ResponseCode.RECORDS_DON_T_EXIST);
        }
        //删除单据信息
        String idsJson = byId.get().getIdsJson();

        List<Long> list = new ArrayList<>();
        if (null == idsJson || "".equals(idsJson)) {
            return Wrapper.fail(ResponseCode.INVOICES_IMPORT_DATA_NOT_ENTITY);
        }
        try {
            list = objectMapper.readValue(idsJson, List.class);
        } catch (JsonProcessingException e) {
            log.error("单据ID集合json转list异常", e);
        }
        //批量查询单据信息
        List<Invoices> allById = invoicesRepository.findAllById(list);
        if (CollectionUtils.isEmpty(allById)) {
            return Wrapper.fail(ResponseCode.RECORDS_DON_T_EXIST);
        }
        //判断是否是未审核数据
        for (Invoices invoices : allById) {
            if (InvoicesTypeConstant.Audit.ALREADY_AUDIT == invoices.getState()) {
                return Wrapper.fail(ResponseCode.IMPORT_BATCHNO_INVOICES_STATE_YET_AUDIT);
            }
        }
        //删除单据详情
        invoicesDetailsRepository.deleteAllByInvoicesIn(allById);
        invoicesRepository.findAllById(list);
        //删除导入批次记录
        invoicesImportBatchNoRepository.findById(request.getId());
        return Wrapper.success();
    }

    /**
     * 添加单据
     *
     * @author wrc
     * @date 2020/7/7
     */
    @Transactional
    @Override
    public Wrapper<Void> invoicesAddOrUpdate(InvoicesAddOrUpdateRequest request, UserLoginCacheDTO sysUser) {
        InvoicesType invoicesType = invoicesTypeRepository.findById(request.getInvoicesTypeId()).orElse(null);
        if (null == invoicesType) {
            return Wrapper.fail("单据类型不存在");
        }
        Warehouse warehouse = warehouseRepository.findById(request.getWarehouseId()).orElse(null);
        if (null == warehouse) {
            return Wrapper.fail("仓库不存在");
        }
        Invoices invoices = new Invoices();
        if(ObjectUtil.isNotNull(request.getId())){
            invoices = invoicesRepository.findById(request.getId()).orElse(null);
            if(ObjectUtil.isNull(invoices)){
                return Wrapper.fail(ResponseCode.RECORDS_DON_T_EXIST);
            }
            if (StateConstant.State.YES_EXAMINE.equals(invoices.getState())) {
                return Wrapper.fail(ResponseCode.INVOICES_TYPE_NOT_UPDATE);
            }
            //删除旧的
            List<InvoicesDetails> details = invoices.getInvoicesDetailsList();
            invoicesDetailsRepository.deleteAll(details);
        }else{
            invoices.setMemberId(sysUser.getMemberId());
            invoices.setMemberRoleId(sysUser.getMemberRoleId());
            invoices.setCreateTime(System.currentTimeMillis());
            invoices.setInvoicesNo(getInvoicesNo("LB"));
            invoices.setState(StateConstant.State.NOT_EXAMINE);
        }
        //保存单据
        BeanUtils.copyProperties(request, invoices);
        invoices.setUpdateTime(System.currentTimeMillis());
        invoices.setInvoicesType(invoicesTypeRepository.findById(request.getInvoicesTypeId()).orElse(null));
        invoices.setWarehouse(warehouseRepository.findById(request.getWarehouseId()).orElse(null));
        invoicesRepository.saveAndFlush(invoices);
        //保存单据明细
        Invoices finalInvoices = invoices;
        List<InvoicesDetails> list = request.getInvoicesDetailsDTOList().stream().map(invoicesDetailsRequest -> {
            InvoicesDetails invoicesDetails = new InvoicesDetails();
            BeanUtils.copyProperties(invoicesDetailsRequest, invoicesDetails);
            invoicesDetails.setInvoices(finalInvoices);
            return invoicesDetails;
        }).collect(Collectors.toList());
        invoicesDetailsRepository.saveAll(list);
        return Wrapper.success();
    }

    /**
     * 查询单据详情
     *
     * @author wrc
     * @date 2020/7/8
     */
    @Override
    public Wrapper<InvoicesDetailsResponse> invoicesDetails(Long id) {
        Invoices invoices = invoicesRepository.findById(id).orElse(null);
        if (ObjectUtil.isNull(invoices)) {
            return Wrapper.fail(ResponseCode.RECORDS_DON_T_EXIST);
        }
        InvoicesDetailsResponse response = new InvoicesDetailsResponse();
        BeanUtils.copyProperties(invoices, response);
        response.setInvoicesTypeId(invoices.getInvoicesType().getId());
        response.setInvoicesTypeName(invoices.getInvoicesType().getName());
        response.setWarehouseId(invoices.getWarehouse().getId());
        response.setWarehouseName(invoices.getWarehouse().getName());
        List<InvoicesDetailsOrderResponse> list = invoices.getInvoicesDetailsList().stream().map(invoicesDetails -> {
            InvoicesDetailsOrderResponse invoicesDetailsOrderResponse = new InvoicesDetailsOrderResponse();
            BeanUtils.copyProperties(invoicesDetails, invoicesDetailsOrderResponse);
            invoicesDetailsOrderResponse.setGoodsGroup(invoicesDetails.getMaterialGroupId() != null ? materialGroupRepository.findById(invoicesDetails.getMaterialGroupId()).map(MaterialGroup::getName).orElse("") : "");
            return invoicesDetailsOrderResponse;
        }).collect(Collectors.toList());
        response.setInvoicesDetailsOrderResponses(list);
        return Wrapper.success(response);
    }

    /**
     * 查询单据详情
     */
    @Override
    public Wrapper<InvoicesDetailsResponse> invoicesDetailsByNo(InvoicesDetailsByNoRequest request) {
        if (null == request) {
            return Wrapper.fail(ResponseCode.WAREHOUSE_NOT_PARAMETER);
        }
        InvoicesDetailsResponse response = new InvoicesDetailsResponse();
        Invoices invoices = null;
        if (null != request.getId()) {
            invoices = invoicesRepository.findById(request.getId()).orElse(null);
        }
        if (!ObjectUtils.isEmpty(request.getDeliveryNo())) {
            invoices = invoicesRepository.findByInvoicesNo(request.getDeliveryNo());
        }
        if (null != request.getStorageNo()) {
            invoices = invoicesRepository.findByInvoicesNo(request.getStorageNo());
        }
        if (null == invoices) {
            return Wrapper.fail(ResponseCode.WAREHOUSE_NOT_PARAMETER);
        }
        List<InvoicesDetails> invoicesDetailss = invoicesDetailsRepository.findByInvoicesIdEquals(invoices.getId());
        BeanUtils.copyProperties(invoices, response);
        List<InvoicesDetailsOrderResponse> collect = invoicesDetailss.stream().map(temp -> {
            InvoicesDetailsOrderResponse invoicesDetailsOrderResponse = new InvoicesDetailsOrderResponse();
            BeanUtils.copyProperties(temp, invoicesDetailsOrderResponse);
            return invoicesDetailsOrderResponse;
        }).collect(Collectors.toList());
        response.setInvoicesDetailsOrderResponses(collect);
        return Wrapper.success(response);
    }

    /**
     * 生成单据编号
     *
     * @author wrc
     * @date 2020/9/12
     */
    private String getInvoicesNo(String str) {
        StringBuilder strBuilder = new StringBuilder(str);
        for (int i = 0; i < 2; i++) {
            strBuilder.append((char) (Math.random() * 26 + 'a'));
        }
        str = strBuilder.toString();
        int number = (int) (Math.random() * 90000) + 10000;
        return str.toUpperCase() + number;
    }


    /**
     * 生成数据导入批次号
     *
     * @author wrc
     * @date 2020/7/3
     */
    public String getBatchNumber() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String date = sdf.format(new Date());
        String number = redisStringUtils.get(redisKey, 0);
        int integer = Integer.parseInt(number == null || "".equals(number) ? "0" : number);
        redisStringUtils.set(redisKey, String.format("%03d", integer + 1), 0);
        return date + String.format("%03d", integer + 1);
    }


    /**
     * 将错误信息输入到txt中
     */
    public String writeErorToTxt(String content) throws Exception {
        File file = File.createTempFile(getBatchNumber(), ".txt");
        getFile(content, file);
        MultipartFile multipartFile = getMulFileByFile(file);
        //上传到云服务器
        Wrapper<String> upload = uploadControllerFeign.upload(multipartFile);
        file.deleteOnExit();
        return upload.getData();
    }


    public static MultipartFile getMulFileByFile(File file) {
        FileItem fileItem = createFileItem(file.getPath(), file.getName());
        return new CommonsMultipartFile(fileItem);
    }

    public static FileItem createFileItem(String filePath, String fileName) {
        String fieldName = "file";
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        FileItem item = factory.createItem(fieldName, "text/plain", false, fileName);
        File newfile = new File(filePath);
        int bytesRead;
        byte[] buffer = new byte[8192];
        try {
            FileInputStream fis = new FileInputStream(newfile);
            OutputStream os = item.getOutputStream();
            while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            fis.close();
        } catch (IOException e) {
            log.error("文件类型转换异常", e);
        }
        return item;
    }


    public void getFile(String writeDate, File file) {
        BufferedWriter out = null;
        OutputStreamWriter osw = null;
        try {
            osw = new OutputStreamWriter(new FileOutputStream(file, true), StandardCharsets.UTF_8);
            out = new BufferedWriter(osw);
            osw.write(writeDate + "\r\n");
            osw.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (osw != null) {
                    osw.close();
                }
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
